home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / dev / c / chunky.lha / lib_chunky / lib-src / c2p.asm next >
Assembly Source File  |  1998-02-25  |  18KB  |  995 lines

  1. ; 100% systemfriendly ChunkyToPlanar converter for use with intuition
  2. ; screens in applications/games/whatever.
  3. ;
  4. ; Coded in 1994 by Morten Eriksen.
  5. ; Reach me through email: mortene@stud.unit.no.
  6. ;
  7. ; Use and modify as you like - give credit where appropriate.
  8. ;
  9. ; Timings on my A1200 with 68EC020 and 32-bit fastram:
  10. ;
  11. ;   Testcase    Dimensions      This routine             C='s WritePixelArray8
  12. ;
  13. ;    1    320x256x5 -    15 frames (0.30 seconds)    33 frames
  14. ;    2    320x256x8 -    16 frames (0.32 seconds)    51 frames
  15. ;    3    640x512x4 -    63 frames (1.26 seconds)    100 frames
  16. ;    4     1024x1024x1 -    194 frames (3.88 seconds)    101 frames
  17. ;    5    752x578x8 -    88 frames (1.76 seconds)    250 frames
  18. ;
  19. ; Please help me speed up this sucker - the main bottleneck is the
  20. ; 'convert32pixels' subroutine (e.g. in the 3rd testcase, 60 out of
  21. ; 63 frames are spent in this routine). As you can see, it gets worse
  22. ; on less bitplanes (compared to C='s routine) - but on 8-bit bitmaps it's
  23. ; about 3 times as fast. If you improve it, be sure to repost the improved
  24. ; version to Usenet, or send it to me through email.
  25. ;
  26. ;------------------------------------------------------------------------------
  27.     xdef    _ChunkyToPlanarAsm
  28. ;------------------------------------------------------------------------------
  29. ; This routine takes a buffer of chunkybytes and transform it into
  30. ; planar datas, which are directly inserted into the destination BitMap.
  31. ;
  32. ; As a replacement for C='s WritePixelArray8 routine, this one is on average
  33. ; about twice as fast and works directly on bitmaps (instead of RastPorts).
  34. ; All cases handled (any width and height > 0, no alignment restrictions).
  35. ; Works on OCS/ECS/AGA, all Kickstarts and any MC680x0 CPU.
  36. ; The downside is that it does not do clipping and does not work with
  37. ; interleaved bitmaps (support for interleaved bitmaps should be piece of
  38. ; cake to implement, though).
  39. ;------------------------------------------------------------------------------
  40. ;
  41. ; C interface:
  42. ;
  43. ; extern void __asm ChunkyToPlanarAsm(register __a0 struct c2pStruct *);
  44. ;
  45. ; struct c2pStruct
  46. ; {
  47. ;  struct BitMap *bmap;
  48. ;  UWORD startX, startY, width, height;
  49. ;  UBYTE *chunkybuffer;
  50. ; } c2p;
  51. ;
  52. ; c2p.bmap = mybitmap;
  53. ; c2p.startX = x0;
  54. ; c2p.startY = y0;
  55. ; c2p.width = x1 - x0 + 1;
  56. ; c2p.height = y1 - y0 + 1;
  57. ; c2p.chunkybuffer = chunkybytes;
  58. ;
  59. ; ChunkyToPlanarAsm(&c2p);
  60. ; CopySBitMap(mywindow->RPort->Layer);
  61. ;------------------------------------------------------------------------------
  62. ;
  63. ; Assembler interface:
  64. ;
  65. ; In:     a0 - c2p struct.
  66. ; Out:    Nothing.
  67. ;------------------------------------------------------------------------------
  68.  
  69. ; ** BitMap struct **
  70. BytesPerRow    EQU    0    ; UWORD
  71. Rows        EQU    2    ; UWORD
  72. Flags        EQU    4    ; UBYTE
  73. Depth        EQU    5    ; UBYTE
  74. Pad        EQU    6    ; UWORD
  75. Planes        EQU    8    ; PLANEPTRs [8]
  76.  
  77. ; ** c2p struct **
  78.  
  79. bmap        EQU    0    ; struct BitMap *
  80. startX        EQU    4    ; UWORD
  81. startY        EQU    6    ; UWORD
  82. width        EQU    8    ; UWORD
  83. height        EQU    10    ; UWORD
  84. chunkybuffer    EQU    12    ; UBYTE *
  85. ;------------------------------------------------------------------------------
  86.     Section    code,CODE
  87.     
  88. _ChunkyToPlanarAsm:
  89.     movem.l    d2-d7/a2-a6,-(sp)
  90.  
  91.     tst.b    madetable        * need only make bitspreadtable once
  92.     bne.s    table_made
  93.     bsr.w    make_table
  94. table_made
  95.  
  96.     * find number of not bytealigned pixels at left side of frame and
  97.     * the mask to be used
  98.     moveq    #0,d0
  99.     move.w    startX(a0),d0
  100.     andi.w    #%111,d0
  101.     tst.w    d0
  102.     beq.s    leadno
  103.     move.w    d0,d1
  104.     moveq    #8,d0
  105.     sub.w    d1,d0
  106.  
  107.     move.b    #$ff,d1
  108.     lsl.b    d0,d1
  109.     move.b    d1,andval_lead
  110.  
  111. leadno    move.w    d0,leadingbits
  112.  
  113.     move.w    width(a0),d0
  114.     cmp.w    leadingbits,d0
  115.     bhs.s    notsingle
  116.  
  117.     * in case the whole chunkypixels buffer to be inserted fits into
  118.     * a single byte
  119.     move.b    #$80,d1
  120.     subq    #1,d0
  121.     asr.b    d0,d1
  122.     addq    #1,d0
  123.     moveq    #8,d2
  124.     sub.w    leadingbits,d2
  125.     lsr.b    d2,d1
  126.     not.b    d1
  127.     move.b    d1,andval_single
  128.     clr.w    trailingbits
  129.     bra.s    single
  130. notsingle
  131.     clr.b    andval_single
  132.  
  133.     * find number of not bytealigned pixels at right side of frame and
  134.     * the mask to be used
  135.     sub.w    leadingbits,d0
  136.     move.w    d0,d1
  137.     andi.w    #$fff8,d1
  138.     sub.w    d1,d0
  139.     move.w    d0,trailingbits
  140.     move.b    #$ff,d1
  141.     lsr.b    d0,d1
  142.     move.b    d1,andval_trail
  143. single
  144.     * initialize variables to be used (modulo, bytealigned width, etc)
  145.     move.l    bmap(a0),a1
  146.     move.l    chunkybuffer(a0),a3
  147.     moveq    #0,d0
  148.     move.b    Depth(a1),d0
  149.     move.w    d0,depth
  150.     move.w    height(a0),Height
  151.     move.w    width(a0),Width
  152.     move.w    leadingbits,d1
  153.     sub.w    d1,Width
  154.     move.w    trailingbits,d1
  155.     sub.w    d1,Width
  156.     move.w    Width,GWidth
  157.     move.w    BytesPerRow(a1),Modulo
  158.     tst.b    andval_single
  159.     bne.s    singlebyte
  160.     move.w    Width,d0
  161.     lsr.w    #3,d0
  162.     sub.w    d0,Modulo
  163. singlebyte
  164.     tst.w    leadingbits
  165.     beq.s    nolead
  166.     sub.w    #1,Modulo
  167. nolead    tst.w    trailingbits
  168.     beq.s    notrail
  169.     sub.w    #1,Modulo
  170. notrail
  171.  
  172.     * find initial offset in bytes into bitmap given by (startX, startY)
  173.     moveq    #0,d0
  174.     move.w    startX(a0),d0
  175.     lsr.w    #3,d0
  176.     move.w    startY(a0),d1
  177.     tst.w    d1
  178.     beq.s    line0
  179.     moveq    #0,d2
  180.     move.w    BytesPerRow(a1),d2
  181.     subq    #1,d1
  182. makeoffset
  183.     add.l    d2,d0
  184.     dbra    d1,makeoffset
  185. line0
  186.     move.l    d0,a2
  187.  
  188.     * find jumpaddress for planar data insertion into bitmap
  189.     * (depending on bitmap depth)
  190.     move.l    a1,a6
  191.     add.l    #Planes,a6
  192.     lea    insertpointerslong,a4
  193.     lea    insertpointers,a5
  194.     moveq    #0,d7
  195.     move.w    depth,d7
  196.     lsl.w    #2,d7
  197.     add.l    d7,a6
  198.     move.l    a6,planepointerspointer
  199.     subq    #4,d7
  200.     add.l    d7,a4
  201.     add.l    d7,a5
  202.     move.l    (a4),insertpointerlong
  203.     move.l    (a5),insertpointer
  204.  
  205.     lea    c2p,a4
  206.  
  207.     ; a0 - c2p struct, a1 - bmap,
  208.     ; a2 - offset from Planes pointer, a3 - chunkybuffer
  209.     ; a4 - bitspread table
  210.  
  211. convertlines
  212.     * check if whole width fits into a single byte and take
  213.     * appropriate action if this is the case
  214.     tst.b    andval_single
  215.     beq.s    testlead
  216.     bsr.w    insertsinglebytebits
  217.     bra.w    trailno
  218.  
  219. testlead
  220.     * is the frame _not_ left bytealigned ?
  221.     tst.w    leadingbits
  222.     beq.b    convert8pixels
  223.     bsr.w    insertleadingbits
  224.  
  225. convert8pixels
  226.     * done?
  227.     tst.w    Width
  228.     beq.s    rowdone
  229.  
  230.     * check if we can do a speedier 32 pixels in one go conversion...
  231.     cmp.w    #32,Width
  232.     blo.s    nolong
  233.     * test odd/even address to be compatible with 68000 aswell *
  234.     move.l    Planes(a1),d0
  235.     add.l    a2,d0
  236.     btst    #0,d0
  237.     bne.s    nolong
  238.     bsr.w    convert32pixels
  239.     sub.w    #32,Width
  240.     addq    #4,a2
  241.     bra.s    convert8pixels
  242.  
  243. nolong    * ...rather than the slower 8 pixel conversion
  244.     moveq    #0,d0
  245.     moveq    #0,d4
  246.     moveq    #8-1,d1
  247. convert8bytes
  248.     * find correct bitspreadtable offset -> a4 *
  249.     moveq    #0,d2
  250.     move.b    (a3)+,d2
  251.     lsl.w    #3,d2
  252.  
  253.     * insert bitrow *
  254.     add.l    d0,d0
  255.     or.l    0(a4,d2.w),d0
  256.     addq    #4,d2
  257.     add.l    d4,d4
  258.     or.l    0(a4,d2.w),d4
  259.  
  260.     dbra    d1,convert8bytes
  261.  
  262.     * spread bits to all registers *
  263.     move.b    d0,d3
  264.     lsr.w    #8,d0
  265.     move.b    d0,d2
  266.     swap    d0
  267.     move.b    d0,d1
  268.     lsr.w    #8,d0
  269.  
  270.     move.b    d4,d7
  271.     lsr.w    #8,d4
  272.     move.b    d4,d6
  273.     swap    d4
  274.     move.b    d4,d5
  275.     lsr.w    #8,d4
  276.  
  277.     cmp.w    #8,depth
  278.     beq.s    its8
  279.     move.l    a2,d7
  280. its8    move.l    planepointerspointer(pc),a6
  281.     move.l    insertpointer(pc),a5
  282.     jsr    (a5)
  283.  
  284.     addq    #1,a2
  285.     subq    #8,Width
  286.     bra.w    convert8pixels
  287.  
  288. rowdone
  289.     * are there any non bytealigned pixels remaining at the right side
  290.     * of the frame?
  291.     tst.w    trailingbits
  292.     beq.b    trailno
  293.     bsr.w    inserttrailingbits
  294.  
  295. trailno    move.w    GWidth,Width
  296.     add.w    Modulo,a2
  297.     subq    #1,Height
  298.     tst.w    Height
  299.     bne.w    convertlines
  300.  
  301.     movem.l    (sp)+,d2-d7/a2-a6
  302.     rts
  303. ;------------------------------------------------------------------------------
  304. insertdata:    * insert converted 8 pixels c->p data into the bitmap
  305. plane8    move.l    -(a6),a5
  306.     add.l    a2,a5
  307.     move.b    d7,(a5)
  308.     move.l    a2,d7
  309. plane7    move.l    -(a6),a5
  310.     move.b    d6,0(a5,d7.l)
  311. plane6    move.l    -(a6),a5
  312.     move.b    d5,0(a5,d7.l)
  313. plane5    move.l    -(a6),a5
  314.     move.b    d4,0(a5,d7.l)
  315. plane4    move.l    -(a6),a5
  316.     move.b    d3,0(a5,d7.l)
  317. plane3    move.l    -(a6),a5
  318.     move.b    d2,0(a5,d7.l)
  319. plane2    move.l    -(a6),a5
  320.     move.b    d1,0(a5,d7.l)
  321. plane1    move.l    -(a6),a5
  322.     move.b    d0,0(a5,d7.l)
  323.     rts
  324. ;------------------------------------------------------------------------------
  325. insertdatalong:    * insert converted 32 pixels c->p data into the bitmap
  326. plane8l    move.l    -(a6),a5
  327.     add.l    a2,a5
  328.     move.l    d7,(a5)
  329.     move.l    a2,d7
  330. plane7l    move.l    -(a6),a5
  331.     move.l    d6,0(a5,d7.l)
  332. plane6l    move.l    -(a6),a5
  333.     move.l    d5,0(a5,d7.l)
  334. plane5l    move.l    -(a6),a5
  335.     move.l    d4,0(a5,d7.l)
  336. plane4l    move.l    -(a6),a5
  337.     move.l    d3,0(a5,d7.l)
  338. plane3l    move.l    -(a6),a5
  339.     move.l    d2,0(a5,d7.l)
  340. plane2l    move.l    -(a6),a5
  341.     move.l    d1,0(a5,d7.l)
  342. plane1l    move.l    -(a6),a5
  343.     move.l    d0,0(a5,d7.l)
  344.     rts
  345. ;------------------------------------------------------------------------------
  346. insertpointer        dc.l